package com.authine.cloudpivot.ext.service.impl;

import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.authine.cloudpivot.ext.applicationservice.base.ApplicationBaseService;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.dto.system.OutApiClientDto;
import com.authine.cloudpivot.ext.model.sales.SalesOrderItemPush;
import com.authine.cloudpivot.ext.model.sales.SalesOrderPush;
import com.authine.cloudpivot.ext.model.yunshu.Attachment;
import com.authine.cloudpivot.ext.model.yunshu.AttachmentsUploadModel;
import com.authine.cloudpivot.ext.model.yunshu.YsRequestModel;
import com.authine.cloudpivot.ext.model.yunshu.YsResultModel;
import com.authine.cloudpivot.ext.service.YunShuService;
import com.authine.cloudpivot.ext.utils.BigDecimalUtils;
import com.authine.cloudpivot.ext.utils.JdbcTemplateUtils;
import com.authine.cloudpivot.ext.utils.StringUtils;
import com.authine.cloudpivot.ext.utils.system.OutApiClientApiUtils;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StopWatch;
import org.springframework.web.client.RestTemplate;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 调用云枢相关服务
 */
@Slf4j
public class YunShuServiceImpl extends ApplicationBaseService implements YunShuService {
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final RestTemplate restTemplate = ApplicationContextUtils.getBean(RestTemplate.class);

    /**
     * 推送采购订单到进销存
     * @param pushDataList
     * @return
     */
    @Override
    public SingleResponse<YsResultModel> pushOrderToInvoicing(String pushDataList) {
        YsRequestModel request = YsRequestModel.builder()
                .actionName("CreatePurchaseOrder")
                .controller("GomroToPSI_Controller")
                .appCode("D000886jinxiaocun")
                .pushDataList(pushDataList)
                .build();

        OutApiClientDto outApiClient = OutApiClientApiUtils.getByGomroUsername("punchout_yunshu");

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        //a2kiikcrsvtkjaqc
        headers.add("EngineCode", outApiClient.getClient_id());
        //vSPrw92R+bPfCAvB0ggyMehB0UcGKlUFLsdTYy16kXBX3e4STqlx7g==
        headers.add("EngineSecret", outApiClient.getClient_secret());

        HttpEntity<YsRequestModel> httpEntity = new HttpEntity<>(request, headers);
        //https://www.h3yun.com/OpenApi/Invoke
        ResponseEntity<YsResultModel> response = restTemplate.postForEntity(outApiClient.getResource_url(), httpEntity, YsResultModel.class);

        try {
            log.warn("ys res:{}", objectMapper.writeValueAsString(response.getBody()));
        } catch (JsonProcessingException e) {
            log.warn("返回参数序列化失败, body:{}，失败信息:{}", Objects.toString(response.getBody(), ""), e);
        }
        return SingleResponse.of(response.getBody());
    }

    @Override
    public void pushOrderToInvoicingListener(List<String> traceIds) {
//        if (!Boolean.TRUE.equals(switchOrderInvoicingPush)) {
//            return;
//        }

        StopWatch stopWatch = new StopWatch();
        stopWatch.start("YunShuOrderListener-createOrder：构建数据");

        if (CollectionUtils.isEmpty(traceIds)) {
            log.warn("YunShuOrderListener：参数为空");
            return;
        }

        List<Map<String, Object>> transportList = JdbcTemplateUtils.builder(ModelConst.T_ORDER_TRACE).selectField("*")
                .in("id", traceIds).queryForList();
        if (CollectionUtils.isEmpty(transportList)) {
            log.warn("YunShuOrderListener：未查到发货记录");
            return;
        }

        String muYuanOrgId = this.getPushOrganizationIdByProfile();
        //判断是否为牧原订单
        String customerOrgId = (String) transportList.get(0).get("order_customer_id");
        if (!muYuanOrgId.equals(customerOrgId)) {
            return;
        }

        List<SalesOrderPush> orderPushes;
        try {
            orderPushes = this.buildOrders(transportList);
        } catch (Exception e) {
            log.warn("YunShuOrderListener：构建推送单构建失败，参数{}，异常详情：{}", transportList, e);
            return;
        }

        String pushDataList;
        try {
            pushDataList = objectMapper.writeValueAsString(orderPushes);
        } catch (JsonProcessingException e) {
            log.warn("YunShuOrderListener：推送单转换JSON字符串失败，参数{}，异常详情：{}", orderPushes, e);
            return;
        }

        stopWatch.stop();
        String prettyPrint = stopWatch.prettyPrint();
        log.info(prettyPrint);

        //只有测试环境才进行推送
        if (!RequestContext.isProd()) {
            //因为需要在测试环境测试推送的参数，但是不需要真正推送给第三方，所以只需要输出构建好的参数即可
            log.info("YunShuOrderListener：推送请求参数{}", pushDataList);
            return;
        }

        SingleResponse<YsResultModel> result = pushOrderToInvoicing(pushDataList);
        if (!result.isSuccess()) {
            log.warn("YunShuOrderListener：推送返回数据未null，可能是内部程序问题，参数{}", pushDataList);
            return;
        }

        log.info("YunShuOrderListener：推送返回数据信息{},请求参数{}", result, pushDataList);
    }

    private String getPushOrganizationIdByProfile() {
        if (RequestContext.isProd()) {
            return "3906";
        }
        return "3901";
    }

    /**
     * 构建推送单
     *
     * @param transportList 发货记录
     * @return 推送单
     */
    private List<SalesOrderPush> buildOrders(List<Map<String, Object>> transportList) {
        if(CollectionUtils.isEmpty(transportList)){
            return null;
        }
        List<String> orderCustomerGoodsIds = transportList.stream().filter(t->!Objects.isNull(t.get("order_customer_goods_id")))
                .map(t->(String)t.get("order_customer_goods_id")).collect(Collectors.toList());
        List<Map<String, Object>> orderCustomerGoods = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).selectField("DISTINCT(relation_id) as relation_id")
                .in("id", orderCustomerGoodsIds).queryForList();
        List<String> relationIds = orderCustomerGoods.stream().map(t->(String)t.get("relation_id")).collect(Collectors.toList());

        List<Map<String, Object>> finalOrderGoodsRelationList = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RELATION).selectField("*")
                .in("id", relationIds).queryForList();

        List<SalesOrderPush> orderPushes = new ArrayList<>();
        transportList.stream().collect(Collectors.groupingBy(t -> t.get("order_customer_id"))).forEach((orderId, values) -> {
            //构建推送单据
//            Map<String, Object> transportFirst = values.get(0);
            Map<String, Object> orderCustomer = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).selectField("*").eq("id", orderId).queryForMap();
//            OrderCustomerExtendsAttr extendsAttr = OrderCustomerExtendsAttr.conversion(transportFirst.getOrderGoods().getVendorOrder().getCustomerOrder().getExtendsAttr(), true);

            SalesOrderPush order = SalesOrderPush.builder()
                    .orderId(Objects.toString(orderId, ""))
                    .phone(Objects.toString(orderCustomer.get("phone"), ""))
                    .erpPO(Objects.toString(orderCustomer.get("erp_po"), ""))
                    .contact(Objects.toString(orderCustomer.get("receiver"), ""))
                    .orderDate(Objects.toString(orderCustomer.get("createdTime"), ""))
                    .address(Objects.toString(orderCustomer.get("address"), ""))
                    .person(Objects.toString(orderCustomer.get("place_order_fullname"), ""))
                    .org(Objects.toString(orderCustomer.get("organization_name"), ""))
                    .details(this.buildItems(values, finalOrderGoodsRelationList))
                    .build();

            orderPushes.add(order);
        });
        return orderPushes;
    }

    /**
     * 构建推送明细
     *
     * @param transportList               发货记录
     * @param finalOrderGoodsRelationList 订单商品关系表
     * @return 推送明细
     */
    private List<SalesOrderItemPush> buildItems(List<Map<String, Object>> transportList, List<Map<String, Object>> finalOrderGoodsRelationList) {
        List<SalesOrderItemPush> items = new ArrayList<>();

        for (Map<String, Object> transport : transportList) {
            Map<String, Object> relationEntity;
            Map<String, Object> orderGoods = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS).selectField("*")
                    .eq("id", transport.get("order_customer_goods_id")).queryForMap();
            Map<String, Object> relation = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RELATION).selectField("*")
                    .eq("id", orderGoods.get("relation_id")).queryForMap();
            if (CollectionUtils.isEmpty(finalOrderGoodsRelationList) || null == relation || relation.isEmpty()) {
                relationEntity = new HashMap<>();
            } else {
                relationEntity = finalOrderGoodsRelationList.stream()
                        .filter(t -> t.get("id").equals(orderGoods.get("relation_id"))).findFirst().orElse(new HashMap<>());
            }

            String csQuantity = "0.0";
            String asQuantity = "0.0";
            String arQuantity = "0.0";
            String atQuantity = "0.0";
            if (BigDecimalUtils.isNull(orderGoods.get("quantity")).compareTo(BigDecimalUtils.isNull(transport.get("quantity")))!=0) {
                csQuantity = Objects.toString(this.getEnableNum((String) orderGoods.get("id")), "");
                asQuantity = Objects.toString(this.getDeliveredNum((String) orderGoods.get("id"), null), "");
                arQuantity = Objects.toString(this.getReceivedNum((String) orderGoods.get("id"), null), "");
                atQuantity = Objects.toString(this.getRefundedNum((String) orderGoods.get("id"), null), "");
            }
            SalesOrderItemPush item = SalesOrderItemPush.builder()
                    .coId(Objects.toString(orderGoods.get("order_customer_id"), ""))
                    .goodsId(Objects.toString(orderGoods.get("id"), ""))
                    .goodsSKU(Objects.toString(orderGoods.get("sku"), ""))
                    .goodsName(Objects.toString(orderGoods.get("name"), ""))
                    .goodsBrand(Objects.toString(orderGoods.get("brand"), ""))
                    .goodsModel(Objects.toString(orderGoods.get("model"), ""))
                    .goodsSpec(Objects.toString(orderGoods.get("spec"), ""))
                    .note(Objects.toString(orderGoods.get("memo"), ""))
                    .describe(Objects.toString(orderGoods.get("description"), ""))
                    //发货数量
                    .quantity(Objects.toString(transport.get("quantity"), ""))
                    .unit(Objects.toString(orderGoods.get("unit"), ""))
                    .dep(Objects.toString(relationEntity.get("demand_department_name"), ""))
                    .inquiry(Objects.toString(relationEntity.get("inquiry_member_name"), ""))
                    .buyer(Objects.toString(orderGoods.get("place_order_fullname"), ""))
                    .area(Objects.toString(relationEntity.get("region"), ""))
                    .company(Objects.toString(relationEntity.get("company"), ""))
                    .warehouse(Objects.toString(relationEntity.get("warehouse"), ""))
                    .clarify(Objects.toString(orderGoods.get("clarify_tips"), ""))
                    .orgName(Objects.toString(transport.get("customer_organization_name"), ""))
                    .csQuantity(csQuantity)
                    .asQuantity(asQuantity)
                    .packageQuantity(Objects.toString(orderGoods.get("package_quantity"), ""))
                    .packageUnit(Objects.toString(orderGoods.get("package_unit"), ""))
                    .arQuantity(arQuantity)
                    .atQuantity(atQuantity)
                    .refundStatus(null)
                    .supplierName(Objects.toString(transport.get("vendor_organization_name"), ""))
                    .uoTime(Objects.toString(orderGoods.get("createdTime"), ""))
                    .requisitioner(Objects.toString(orderGoods.get("requisitioner"),""))
                    .build();
            items.add(item);
        }

        return items;
    }

    /**
     * 推送数据到氚云
     *
     * @param pushDataList 请求参数
     * @return 推送返回信息
     */
    public SingleResponse<YsResultModel> pushDataToYunShu(String pushDataList) {


        OutApiClientDto outApiClient = OutApiClientApiUtils.getByGomroUsername("punchout_yunshu");

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("EngineCode", outApiClient.getClient_id());
        headers.add("EngineSecret", outApiClient.getClient_secret());
        HttpEntity<String> httpEntity = new HttpEntity<>(pushDataList, headers);

        log.info("转采订单推送氚云请求参数:{}", pushDataList);
        ResponseEntity<String> response = restTemplate.postForEntity(outApiClient.getResource_url(), httpEntity, String.class);
        YsResultModel ysRequest = null;

        try {
            log.info("氚云返回参数:{}", response.getBody());

            ysRequest = objectMapper.readValue(response.getBody(), YsResultModel.class);

        } catch (JsonProcessingException e) {
            log.warn("返回参数序列化失败, body:{}，失败信息:{}", Objects.toString(response.getBody(), ""), e);
        }
        return SingleResponse.of(ysRequest);
    }

    /**
     * 推送附件到氚云
     *
     * @param fileUpload 请求参数
     * @return 推送返回信息
     */
    public YsResultModel pushAttachmentToYunShu(AttachmentsUploadModel fileUpload) {

        //获取平台维护的client
        OutApiClientDto outApiClient = OutApiClientApiUtils.getByGomroUsername("punchout_yunshu");

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        headers.add("EngineCode", outApiClient.getClient_id());
        headers.add("EngineSecret", outApiClient.getClient_secret());
        StringBuilder url = new StringBuilder("https://webapp.gomro.cn/OpenApi/UploadAttachment?");

        url.append("SchemaCode=").append(fileUpload.getSchemaCode()).append("&FilePropertyName=").append(fileUpload.getFilePropertyName()).append("&BizObjectId=").append(fileUpload.getBizObjectId());

        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
        for (Attachment attachment : fileUpload.getAttachments()) {
            try {
                if (!StringUtils.isBlank(attachment.getUrl())){
                    //读取远程地址附件信息
                    URL openUrl = new URL(attachment.getUrl());
                    URLConnection urlConnection = openUrl.openConnection();
                    int fileLength = urlConnection.getContentLength();
                    // 读取流信息，一次性写入字节数组（与下面正确示例中不同之处）
                    InputStream inputStream = urlConnection.getInputStream();
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    byte[] buffer = new byte[fileLength];

                    while ((fileLength = inputStream.read(buffer)) != -1) {
                        bos.write(buffer, 0, fileLength);
                    }
                    inputStream.close();
                    bos.close();
                    ByteArrayResource fileSystemResource = new ByteArrayResource(bos.toByteArray()) {
                        @Override
                        public String getFilename() {
                            //重写文件名称,不重写会报错
                            return attachment.getName();
                        }
                    };
                    form.add("file",fileSystemResource);
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        YsResultModel ysRequest = null;

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(form, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(url.toString(), httpEntity, String.class);

        try {
            ysRequest = objectMapper.readValue(response.getBody(), YsResultModel.class);

        } catch (IOException e) {
            log.warn("返回参数序列化失败, body:{}，失败信息:{}", Objects.toString(response.getBody(), ""), e);
        }
        return ysRequest;
    }
}
